package org.dwell.urlfilter.demo.realm;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.dwell.urlfilter.demo.domain.CoreModule;
import org.dwell.urlfilter.demo.domain.CoreRole;
import org.dwell.urlfilter.demo.domain.CoreUser;
import org.dwell.urlfilter.demo.exception.EmptyAccountException;
import org.dwell.urlfilter.demo.service.CoreModuleService;
import org.dwell.urlfilter.demo.service.CoreRoleService;
import org.dwell.urlfilter.demo.service.CoreUserService;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Jange on 2016/4/6.
 */
public class WebManagerUserAuthRealm  extends AuthorizingRealm {

    private final static Logger LOG = Logger.getLogger(WebManagerUserAuthRealm.class.getName());

    @Autowired
    private CoreUserService coreUserService;
    @Autowired private CoreRoleService coreRoleService;
    @Autowired
    private CoreModuleService coreModuleService;

    /**
     * 针对需要授权才能访问的资源，当用户访问的时候会进入这个方法。
     *
     * 授权信息
     * 是负责在应用程序中决定用户的访问控制的方法。
     * 它是一种最终判定用户是否被允许做某件事的机制。
     * 与doGetAuthenticationInfo(AuthenticationToken token)相似，
     * doGetAuthorizationInfo(PrincipalCollection principals)
     * 也知道如何协调多个后台数据源来访问角色恶化权限信息和准确地决定用户是否被允许执行给定的动作。
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username=(String)principals.fromRealm(getName()).iterator().next();
        if( username != null ){
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
            CoreUser subject = coreUserService.findByUsername(username);

            List<CoreRole> roles = coreRoleService.listByUserId(subject.getUserId());
            System.out.println("doGetAuthorizationInfo ~ roles = " + roles);
            List<CoreModule> resources = null;
            List<String> permissions = null;
            for (CoreRole role : roles) {
                info.addRole(role.getRoleName());
                resources = this.coreModuleService.listByRoleId(role.getRoleId());
                permissions = new ArrayList<String>();
                for(CoreModule resource : resources) {
                    System.out.println(resource.getModuleUrl() + " - " + resource.getPermission());
                    permissions.add(resource.getPermission());
                    info.addStringPermissions(permissions);
                }
            }
            return info;
        }

        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
        LOG.info("doGetAuthenticationInfo username : "+token.getUsername());
        String userName = token.getUsername();
        CoreUser user = null;
        if(userName == null || "".equals(userName)){
            throw new EmptyAccountException("用户名不能为空");
        }
        try{
            user = coreUserService.findByUsername(userName);
        }catch(Exception e){
            e.printStackTrace();
            throw new RuntimeException("查询用户数据失败");
        }

        if(user == null){
            throw new UnknownAccountException("用户名不存在");
        }
        if(!user.getPassword().equals(String.valueOf(token.getPassword()))){
            throw new IncorrectCredentialsException("用户名/密码错误");
        }
        Subject currentUser = SecurityUtils.getSubject();
        currentUser.getSession().setAttribute("_SESSION_USER_", user);
        return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(), getName());
    }
}
